package com.ys.service.finance.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.config.MenuId;
import com.ys.dto.AddDto;
import com.ys.entity.finance.TcwDepositPlatform;
import com.ys.entity.finance.TcwWanliCurrencyExchange;
import com.ys.entity.finance.TcwWanliCurrencyExchangeItem;
import com.ys.entity.finance.TcwWanliFinance;
import com.ys.entity.flow.YspModel;
import com.ys.entity.sys.TsUserChange;
import com.ys.entity.sys.YsCol;
import com.ys.entity.sys.YsMenu;
import com.ys.enume.finance.PaymentEnum;
import com.ys.enume.flow.FlowEnum;
import com.ys.enume.sys.RegexUtilEnum;
import com.ys.mapper.business.DiySqlMapper;
import com.ys.mapper.finance.TcwWanliCurrencyExchangeItemMapper;
import com.ys.mapper.finance.TcwWanliCurrencyExchangeMapper;
import com.ys.service.finance.TcwAccountCountForWanliService;
import com.ys.service.finance.TcwWanliCurrencyExchangeService;
import com.ys.service.flow.YspTaskService;
import com.ys.util.CheckUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service("TcwWanliCurrencyExchangeService")
public class TcwWanliCurrencyExchangeServiceImpl implements TcwWanliCurrencyExchangeService {


    @Autowired
    private TcwWanliCurrencyExchangeMapper tcwWanliCurrencyExchangeMapper;

    @Autowired
    private TcwWanliCurrencyExchangeItemMapper tcwWanliCurrencyExchangeItemMapper;

    @Autowired
    private YspTaskService yspTaskService;

    @Autowired
    private CheckUtil checkUtil;

    @Autowired
    private DiySqlMapper diySqlMapper;

    @Autowired
    private TcwAccountCountForWanliService tcwAccountCountForWorldFirstService;


    /**
     * 新增万里汇货币兑换
     * @param params
     * @param subData
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R add(Map<String, Object> params, String subData) throws Exception {
        //验证
        String msg = yzMsg(params);
        if (msg != null){
            return R.error(msg);
        }
        TcwWanliCurrencyExchange tcwWanliCurrencyExchange = JSON.parseObject(JSON.toJSONString(params), TcwWanliCurrencyExchange.class);
        if (new TcwWanliCurrencyExchange().setBid(tcwWanliCurrencyExchange.getBid()).count() != 0){
            return R.error("该单号已存在，核实后再操作!");
        }
        // 验证是否有详情数据
        JSONArray detailJA = JSON.parseArray(subData);
        if (detailJA == null || detailJA.size() == 0) {
            return R.error("详情数据不能为空");
        }

        String loginUserId = ShiroUtils.getUserId();
        TsUserChange tsUserChange = new TsUserChange().setUserId(loginUserId).setStatus(1).queryFirst();

        tcwWanliCurrencyExchange.setStatus(0);
        tcwWanliCurrencyExchange.setCreateChangeId(String.valueOf(tsUserChange.getId()));
        tcwWanliCurrencyExchange.setEffectStock(FlowEnum.EffectStock.NOT_EFFECT.value);
        tcwWanliCurrencyExchangeMapper.insert(tcwWanliCurrencyExchange);

        for (int i = 0; i < detailJA.size(); i++) {
            JSONObject detailJO = detailJA.getJSONObject(i);
            if(detailJO.get("hcAmount") == null){
                throw new RuntimeException("兑出金额不能为空,不允许保存!");
            }else if (detailJO.get("hcAmount").toString().trim().equals("")){
                throw new RuntimeException("兑出金额不能为空,不允许保存!");
            }
            if(detailJO.get("hcAmount").toString().equals("0")){
                throw new RuntimeException("兑出金额不能为0,不允许保存!");
            }
            if(detailJO.get("hrAmount") == null){
                throw new RuntimeException("兑入金额不能为空,不允许保存!");
            }else if (detailJO.get("hrAmount").toString().trim().equals("")){
                throw new RuntimeException("兑入金额不能为空,不允许保存!");
            }
            if(detailJO.get("hrAmount").toString().equals("0")){
                throw new RuntimeException("兑入金额不能为0,不允许保存!");
            }
            //不能超过两位小数点
            String regular2 = RegexUtilEnum.DefaultValue.TWO_DECIMAL_POINTS.value;
            Pattern pattern = Pattern.compile(regular2);

            //3.获取对应的匹配器
            Matcher matcher = pattern.matcher(detailJO.get("hcAmount").toString());
            if (!matcher.matches()){
                throw new RuntimeException("兑出金额只允许填写小数点两位数的金额,核实后再操作!");
            }

            matcher = pattern.matcher(detailJO.get("hrAmount").toString());
            if (!matcher.matches()){
                throw new RuntimeException("兑入金额只允许填写小数点两位数的金额,核实后再操作!");
            }
            TcwWanliCurrencyExchangeItem tcwWanliCurrencyExchangeItem = JSON.parseObject(JSON.toJSONString(detailJO), TcwWanliCurrencyExchangeItem.class);
            tcwWanliCurrencyExchangeItem.setCurrencyExchangeBid(tcwWanliCurrencyExchange.getBid());
            tcwWanliCurrencyExchangeItem.setExchangeRate(tcwWanliCurrencyExchangeItem.getHrAmount().divide(tcwWanliCurrencyExchangeItem.getHcAmount(),4, BigDecimal.ROUND_HALF_UP));//保留4位小数，四舍五入
            tcwWanliCurrencyExchangeItemMapper.insert(tcwWanliCurrencyExchangeItem);
        }
        YsMenu ysMenu = new YsMenu().setId(MenuId.TCW_WanliCurrencyExchange).queryFirst();
        if (ysMenu.getFlowModelId().longValue() != 0L) {
            YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
            String codeModel = yspModel.getCode();
            String createUserId = ShiroUtils.getUserId();
            yspTaskService.init(codeModel, tcwWanliCurrencyExchange.getBid(), createUserId);
        }

        return R.ok(AddDto.gotoEdit("/web/finance/tcwWanliCurrencyExchange/toEdit?bid=" + tcwWanliCurrencyExchange.getBid()));
    }


    /**
     * 修改万里汇货币兑换
     * @param params
     * @param subData
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R edit(Map<String, Object> params, String subData) throws Exception {
        //验证
        String msg = yzMsg(params);
        if (msg != null){
            return R.error(msg);
        }
        TcwWanliCurrencyExchange tcwWanliCurrencyExchange = JSON.parseObject(JSON.toJSONString(params), TcwWanliCurrencyExchange.class);
        if (new TcwWanliCurrencyExchange().setBid(tcwWanliCurrencyExchange.getBid()).where("A.id != " + tcwWanliCurrencyExchange.getId()).count() != 0){
            return R.error("该单号已存在，核实后再操作!");
        }
        // 验证是否有详情数据
        JSONArray detailJA = JSON.parseArray(subData);
        if (detailJA == null || detailJA.size() == 0) {
            return R.error("详情数据不能为空");
        }

        //判断是否实在制单中
        Integer flowState = yspTaskService.flowState(tcwWanliCurrencyExchange.getBid());

        if (flowState != 0){
            return R.error("万里汇货币兑换单不是制单中,不允许保存!");
        }

        tcwWanliCurrencyExchangeMapper.update(tcwWanliCurrencyExchange);

        diySqlMapper.deleteTcwWanliCurrencyExchangeBid(tcwWanliCurrencyExchange.getBid());

        for (int i = 0; i < detailJA.size(); i++) {
            JSONObject detailJO = detailJA.getJSONObject(i);
            if(detailJO.get("hcAmount") == null){
                throw new RuntimeException("兑出金额不能为空,不允许保存!");
            }else if (detailJO.get("hcAmount").toString().trim().equals("")){
                throw new RuntimeException("兑出金额不能为空,不允许保存!");
            }
            if(detailJO.get("hcAmount").toString().equals("0")){
                throw new RuntimeException("兑出金额不能为0,不允许保存!");
            }
            if(detailJO.get("hrAmount") == null){
                throw new RuntimeException("兑入金额不能为空,不允许保存!");
            }else if (detailJO.get("hrAmount").toString().trim().equals("")){
                throw new RuntimeException("兑入金额不能为空,不允许保存!");
            }
            if(detailJO.get("hrAmount").toString().equals("0")){
                throw new RuntimeException("兑入金额不能为0,不允许保存!");
            }
            //不能超过两位小数点
            String regular2 = RegexUtilEnum.DefaultValue.TWO_DECIMAL_POINTS.value;
            Pattern pattern = Pattern.compile(regular2);

            //3.获取对应的匹配器
            Matcher matcher = pattern.matcher(detailJO.get("hcAmount").toString());
            if (!matcher.matches()){
                throw new RuntimeException("兑出金额只允许填写小数点两位数的金额,核实后再操作!");
            }

            matcher = pattern.matcher(detailJO.get("hrAmount").toString());
            if (!matcher.matches()){
                throw new RuntimeException("兑入金额只允许填写小数点两位数的金额,核实后再操作!");
            }
            TcwWanliCurrencyExchangeItem tcwWanliCurrencyExchangeItem = JSON.parseObject(JSON.toJSONString(detailJO), TcwWanliCurrencyExchangeItem.class);
            tcwWanliCurrencyExchangeItem.setCurrencyExchangeBid(tcwWanliCurrencyExchange.getBid());
            tcwWanliCurrencyExchangeItem.setExchangeRate(tcwWanliCurrencyExchangeItem.getHrAmount().divide(tcwWanliCurrencyExchangeItem.getHcAmount(),4, BigDecimal.ROUND_HALF_UP));//保留4位小数，四舍五入
            tcwWanliCurrencyExchangeItemMapper.insert(tcwWanliCurrencyExchangeItem);
        }
        return R.ok(AddDto.gotoEdit("/web/finance/tcwWanliCurrencyExchange/toEdit?bid=" + tcwWanliCurrencyExchange.getBid()));
    }

    /**
     * 货币兑换流转
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R flowPass(Long id, String loginUserId) throws Exception {
        TcwWanliCurrencyExchange entity = new TcwWanliCurrencyExchange().setId(id).queryFirst();
        String bid = entity.getBid();
        try {
            Flow f = yspTaskService.flowPass(bid, loginUserId);
            if (f.getCode() == Flow.Code.FAILED.value) {
                return R.error(f.getMsg());
            } else {
                if (f.getState() == Flow.State.FINISH.value) {
                    R r = flowFinish(entity);
                    if (r.getCode() == 1) {
                        return R.error(r.getMsg());
                    }
                }
                return R.ok();
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 删除货币兑换
     * @param id 主键id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R del(Long id) throws Exception {
        TcwWanliCurrencyExchange tcwWanliCurrencyExchange = new TcwWanliCurrencyExchange().setId(id).queryFirst();
        if (tcwWanliCurrencyExchange == null){
            throw new RuntimeException("万里汇货币兑换单据不存在,请核实后再操作!");
        }

        //判断是否实在制单中
        Integer flowState = yspTaskService.flowState(tcwWanliCurrencyExchange.getBid());

        if (flowState != 0){
            throw new RuntimeException("万里汇货币兑换单不是制单中,不允许删除!");
        }

        yspTaskService.flowDelete(tcwWanliCurrencyExchange.getBid(),tcwWanliCurrencyExchange.getCreateChangeId());

        tcwWanliCurrencyExchangeMapper.deleteTrue(id);

        diySqlMapper.deleteTcwWanliCurrencyExchangeBid(tcwWanliCurrencyExchange.getBid());

        return R.ok("删除成功!");
    }



    private String yzMsg(Map<String, Object> infoMap){
        //验证导入字段
        String backMsg = "";
        //获取pc字段数据
        List<YsCol> listField = new YsCol()
                .where("A.MenuId = "+ MenuId.TCW_WanliCurrencyExchange)
                .setOrderby("A.SortNo ASC")
                .queryList();
        //验证必填字段的非空；其他字段的长度限制、类型
        try {
            backMsg = checkUtil.checkTableColLengthAndDataType(
                    "TCW_WanliCurrencyExchange",
                    listField,
                    infoMap,
                    ysColItem->ysColItem.getFormEditRequired()!=null && ysColItem.getFormEditRequired() == 1
            );
            if(backMsg!=null && !"".equals(backMsg)){//若有误，则跳过这条信息
                return backMsg;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public R flowFinish(TcwWanliCurrencyExchange entity) throws Exception {
        entity.setEffectStock(1);
        entity.setCurrencyExchangeType(PaymentEnum.StatePay.SUCCESS.value);
        tcwWanliCurrencyExchangeMapper.update(entity);

        //查询收款平台账户
        TcwDepositPlatform tcwDepositAccount = new TcwDepositPlatform().setId(entity.getDepositAccountId()).queryFirst();
        if (tcwDepositAccount == null){
            throw new RuntimeException("收款平台账户不存在!");
        }
        //查询万里汇账户资金 TODO 先用code  在更改到mid
        TcwWanliFinance tcwWorldFirstFinance = new TcwWanliFinance().setDepositPlatformCode(tcwDepositAccount.getCode()).queryFirst();
        if (tcwWorldFirstFinance == null){
            throw new RuntimeException("万里汇账户资金不存在!");
        }

        List<TcwWanliCurrencyExchangeItem> tcwWanliCurrencyExchangeList = new TcwWanliCurrencyExchangeItem().setCurrencyExchangeBid(entity.getBid()).queryList();
        if (tcwWanliCurrencyExchangeList.size() == 0){
            throw new RuntimeException("万里汇货币兑换子件数据为空,数据异常!");
        }
        for (TcwWanliCurrencyExchangeItem tcwWanliCurrencyExchangeItem : tcwWanliCurrencyExchangeList){
            //兑出流水
            R add = tcwAccountCountForWorldFirstService.add(false, tcwDepositAccount.getCode(),
                    tcwWanliCurrencyExchangeItem.getHcCurrency(), 4,entity.getBid(), tcwWanliCurrencyExchangeItem.getHcAmount().negate()
                    , "单号:" + entity.getBid() + ",备注:" + entity.getVbz() + ",汇率:" + tcwWanliCurrencyExchangeItem.getExchangeRate());
            if (add.getCode() == 1){
                throw new RuntimeException(add.getMsg());
            }
            //兑入流水
            R add1 = tcwAccountCountForWorldFirstService.add(false, tcwDepositAccount.getCode(),
                    tcwWanliCurrencyExchangeItem.getHrCurrency(), 4,entity.getBid(), tcwWanliCurrencyExchangeItem.getHrAmount()
                    , "单号:" + entity.getBid() + ",备注:" + entity.getVbz() + tcwWanliCurrencyExchangeItem.getExchangeRate() + "(兑出币种:" + tcwWanliCurrencyExchangeItem.getHcCurrency() + ",兑换,兑入币种:" + tcwWanliCurrencyExchangeItem.getHrCurrency() + ",汇率:" + tcwWanliCurrencyExchangeItem.getExchangeRate());
            if (add1.getCode() == 1){
                throw new RuntimeException(add1.getMsg());
            }
        }
        return R.ok();
    }


    //获取列表数据
    @Override
    @Transactional
    public Map<String,Object> getExtraParam( String bid) throws Exception{
        Map entity = new TcwWanliCurrencyExchange().setBid(bid)
                .addLeftJoin("YS_ProcInst Ysp ON Ysp.bid = A.bid")//流程表
                .addField("FORMAT(Ysp.UpdateTime, 'yyyy-MM-dd hh:mm:ss') AS updateTime1")//审核时间
                .addLeftJoin("TCW_DepositPlatform tda ON tda.id = A.DepositAccountId")//收款账户平台
                .addField("tda.id AS depositAccountId,tda.platformName AS platformName,tda.code AS depositAccountCode,tda.name AS depositAccountName")
                .addLeftJoin("TB_CompanyInfo tci ON tci.vid = tda.CompanyVid ")//公司
                .addField("tci.vname AS companyName")
                .queryFirstMap();
        entity.remove("createTime");
        return entity;
    }
    //获取子列表数据
    @Override
    @Transactional
    public List<Map<String, Object>> getItemList( String bid) throws Exception{
        List<Map<String, Object>> sonlist = new TcwWanliCurrencyExchangeItem()
                .setCurrencyExchangeBid(bid)
                .queryMap();
        return sonlist;
    }




}
